$(function() {
	//confirm box for save action
	declareConfirmBox('comfirmDialogHandler');
	//confrim box for refresh action
	declareConfirmBox('reloadButtonHandler','reload-confirm-box');
	//declareAlertDialog
	declareAlertDialog('Please fill available rows or check the format of the link!','returnToEditMode');
	//declareAlertDialog error
	declareAlertDialog('There are some errors on server! Your data have not been saved!','returnToEditMode','save-error-dialog');
	
	//declareAlertDialog error
	declareAlertDialog('Please input file path only. Folder path is not supported!','returnToEditMode','filepath-error-dialog');
	
});

/**
 * Predefined values
 */
var gridId = "s3list";
var jQGridId = "#"+gridId;
var pagerId = "#llPager";
var updateLink = "updateLinks.do";
var loadLink = "loadLinkList.do";
var saveAllButtonId = 'saveAllButton';
var addButtonId	= 'addButon';
var reloadButtonId = 'reloadButton';
var firstButtonColumnIndex = 0;
var nextRowId = -1;
var emptyFieldMessage = "Invalid value! You must fill all value!";
var invalidURLMessage = "Some URLs are not in correct format!";
/**
 * Utility variable
 */
var listEditedRowID = new Array();
var activeGrid = true;
var oldDataList = new Array();
var inValidRowId = new Array();

/**
 * Create table for fx Factor
 * @param linkListModel
 * @param param
 */
function populateLinkedTable(linkListModel) {
	var grid = jQuery(jQGridId);
		grid.jqGrid(
				{
					url : loadLink,
					datatype : "json",
					height: '100%',
					colNames : linkListModel.colNames,
					colModel : linkListModel.colModel,
					mtype : "POST",
					pager : pagerId,
					viewrecords : true,
					rownumbers : true,
					gridview : true,
//					autowidth: true,
//					shrinkToFit: true,
					editurl:'clientArray',
					caption: 'Link List',
					sortname: 'Order',
					sortable:true,
					sortorder: 'asc',
					loadonce:true,
					ondblClickRow: function (rowId, iRow, iCol, e)
					{
						if (iCol<firstButtonColumnIndex)
							onRowDbClickHandler(rowId);
					},
					loadComplete: function()
					{
						onLoadCompleteHandler();
					}
					,
					beforeSelectRow: function (rowId, e) {
						var iCol = $.jgrid.getCellIndex(e.target);
						beforeSelectRowHandler(grid,iCol, rowId);
	                }
				});
		addButtonToPager();
		firstButtonColumnIndex = getColumnIndexByName(grid,'clear');
	
}

/**
 * This function will execute when user double click on any row of the grid
 * If the row is not in edit mode and the grid is ready, change the row to edit mode
 * and enable Save all button at the pager of the grid
 * @param rowId
 */
function onRowDbClickHandler(rowId)
{
	// this row is not in edit mode
	if (activeGrid && !isEditting(rowId) ) {
		//save current data
		addDataToOldData(rowId);
		//remember this row 
		markEditRow(rowId);
		//set status of row to update
		var status = getGridData(gridId,rowId).Status;
		if (status != 2)
			setRowStatus(rowId, 1);
		unRemoveRow(rowId);
		// change this row to edit mode
		jQuery("#"+gridId).jqGrid('editRow',rowId);
	}
}

/**
 * This function will be execute when the data of the list has been loaded and before the render of the grid
 * Restore the listEditedRowID
 * Disable Save all button at the pager of the grid
 */
function onLoadCompleteHandler()
{
//	disableCustomButton(saveAllButtonId);
	enableCustomButton(reloadButtonId);
	setRemoveRow();
	markAsInvalid(inValidRowId);
	activeGrid = true;
}

/**
 * This function will execute when user click on the row
 * If the clicked column is clear column, the data of selected row will be restored
 * If the clicked column is remove column, the row will be marked as temp data
 * If the clicked column is MoveUp/MoveDown, the row will be move accordingly
 * Nothing happen in the other cases
 */
function beforeSelectRowHandler(grid,iCol, rowId)
{
    if (iCol >= firstButtonColumnIndex && activeGrid) {
    	//enable save button
		enableCustomButton(saveAllButtonId);
        if (iCol == firstButtonColumnIndex)
        	{
        		jQuery(jQGridId).jqGrid('restoreRow',rowId);
        		//check old data list
        		removeFromOdlDataList(rowId);
        		//check EditedRowIdlist
        		listEditedRowID = removeOutOfList(rowId,listEditedRowID);
        		//removeFromInvalidRow
        		inValidRowId = removeOutOfList(rowId,inValidRowId);
        		markValidRow(rowId);
        		if (parseInt(getGridData(gridId,rowId).Status) != 2 )
        			setRowStatus(rowId, 1);
        		unRemoveRow(rowId);
        	}
        else if (iCol == firstButtonColumnIndex+1)
        	{
        		//check EditedRowIdlist
        		listEditedRowID = removeOutOfList(rowId,listEditedRowID);
    			//restore Row
    			jQuery(jQGridId).jqGrid('saveRow',rowId);
        		setRowStatus(rowId, -1);
        		markRemovedRow(rowId);
        		//removeFromInvalidRow
        		inValidRowId = removeOutOfList(rowId,inValidRowId);
        		markValidRow(rowId);
        	}
        else if (iCol == firstButtonColumnIndex+2)
        	{
        		moveRow(rowId, -1);
        	}
        else if (iCol == firstButtonColumnIndex+3)
        	{
        		moveRow(rowId, 1);
        	}
    }
 // prevent row selection if one click on the button
    return false;
}

/**
 * This function will add button to the pager of the grid
 */
function addButtonToPager()
{
	jQuery(jQGridId).jqGrid('navGrid', pagerId, {
		edit : false,
		add : false,
		del : false,
		search : false,
		refresh : false
	});
	addCustomButton(reloadButtonId,"Refesh","ui-icon-refresh",'openConfirmBox("reload-confirm-box");');
	addCustomButton(addButtonId,"Add","ui-icon-plus",'addButtonHandler();');
	addCustomButton(saveAllButtonId,"Save All","ui-icon-disk",'openConfirmBox();');	
	disableCustomButton(saveAllButtonId);
	
}


/**
 * This function will send JSON data which represent grid data to url
 * @param url
 */
function sendData(url)
{
		var gridIds = $(jQGridId).jqGrid("getDataIDs");
		var sendData = parseData(gridId,gridIds);
		showSavingMessage(gridId);
		activeGrid = false;
		disableCustomButton(saveAllButtonId);
		disableCustomButton(reloadButtonId);
		disableCustomButton(addButtonId);
			$.ajax({
		        type: "POST", 		
		        url: url, 		
		        data: {linkTable:sendData},
		        processdata: true, 	
		        dataType: 'json',
		        success: function (response) {
		        	hideSavingMessage(gridId);
		        	enableCustomButton(saveAllButtonId);
		        	enableCustomButton(reloadButtonId);
		        	$(".loading").css("display", "none");
		        	
		        	if (response == null) {
		        		//reload page
						document.location.reload(true);
		        	} else if (!response.success) {
						//declareAlertDialog error
						declareAlertDialog(response.message,'returnToEditMode',response.id);
						openAlert(response.id);
					}
		        },
		        error: function(e)
		        {
		        	hideSavingMessage();
		        	enableCustomButton(saveAllButtonId);
		        	enableCustomButton(reloadButtonId);
		        	$(".loading").css("display", "none");
		        	openAlert('save-error-dialog');
		        }
		    });
}

/**
 * This is the utility function which changes all row which are in the @listEditedRowID to edit mode
 */
function returnToEditMode()
{
	//change row in listEditedRowID to edit mode
	for (var i=0;i<listEditedRowID.length;++i)
	{
		$(jQGridId).jqGrid('editRow',listEditedRowID[i]);
	}
}

/**
 * This is the utility function which remove row with @rowId out of @oldDataList
 */
function removeFromOdlDataList(rowId)
{
	for (var i=0; i< oldDataList.length; ++i)
	{
		var obj = oldDataList[i];
		if (obj.id === rowId)
			{
				$(jQGridId).jqGrid('setRowData',rowId,obj.data);
				oldDataList.splice(i, 1);
			}
	}
}


/**
 * The function will execute when user click OK button of confirm box
 */
function comfirmDialogHandler()
{
	saveAllEdittingRow();
	//validate data before saving
	if (!validateData())
		{
			
			
		}
	else
		{
			sendData(updateLink);
//			returnToEditMode();
		}
}

/**
 * This function executes when user click on add button at the pager of grid
 */
function addButtonHandler()
{
	var rowId = nextRowId+"";
	var newOrder = jQuery(jQGridId).jqGrid('getGridParam', 'records')+1;
	var datarow = {Id: rowId, Title: "", Link: "", Order: newOrder, Status: "2"};
	addNewRow(gridId, datarow, rowId);
	oldDataList.push({id: rowId, data:datarow});
	markEditRow(rowId);
	--nextRowId;
}

/**
 * This is the utility function. It add @rowId to listEditedRowID and enable SaveAllButton
 */
function markEditRow(rowId)
{
	// mark this row
	listEditedRowID.push(rowId);
	//enable save button
	enableCustomButton(saveAllButtonId);
}

/**
 * This is the utility function which supports change the status value of the row
 */
function setRowStatus(rowId, newStatus)
{
	$(jQGridId).jqGrid('setRowData',rowId,{Status:newStatus});
}

/**
 * This is the utility function which supports store row data to temp list
 */
function addDataToOldData(rowId)
{
	var data= {id:rowId,data:getGridData(gridId,rowId)};
	oldDataList.push(data);
}

/**
 * This function will handle moving row with @rowId to next position based on interval
 * @param rowId
 * @param interval
 */
function moveRow(rowId,interval)
{
	//save all editting row
	saveAllEdittingRow();
	//check if the selected row is currently in edit mode
	var thisData = getGridData(gridId,rowId);
	var nextPosRowId = findRow((parseInt(thisData.Order)+interval)+"");
	var nextPosData = getGridData(gridId,nextPosRowId);
	if (nextPosRowId != null)
		{
			//swap order
			var tempOrder = thisData.Order;
			thisData.Order = nextPosData.Order;
			nextPosData.Order = tempOrder;
			//apply new order
			$(jQGridId).jqGrid('setRowData',rowId,thisData);
			$(jQGridId).jqGrid('setRowData',nextPosRowId,nextPosData);
			//refesh grid
			reloadOnClientSide();
		}
	
	//update old data list 
	updateStorageOrder(rowId,thisData.Order);
	updateStorageOrder(nextPosRowId,nextPosData.Order);
	//return to edit mode
	returnToEditMode();
	//update row status
	if (thisData.Status == 0)
		setRowStatus(rowId,1);
	if (nextPosData.Status == 0)
		setRowStatus(nextPosRowId,1);
}

/**
 * Return rowId based on its order
 * @param order
 * @returns
 */
function findRow(order)
{
	var gridIds = $(jQGridId).jqGrid("getDataIDs");
	for (var i=0; i<gridIds.length;++i)
		{
			if (getGridData(gridId,gridIds[i]).Order === order)
				return gridIds[i];
		}
	return null;
}

/**
 * Check if the row is currently in edit mode or not
 * @param rowId
 */
function isEditting(rowId)
{
	if ($("tr#"+rowId).attr("editable") === "1")
		return true;
	return false;
}

/**
 * Update order of row @rowId in oldDataList
 */
function updateStorageOrder(rowId,newOrder)
{
	for (var i=0; i<oldDataList.length;++i)
		{
			if (parseInt(oldDataList[i].id) == parseInt(rowId))
				{
					oldDataList[i].data.Order = newOrder;
					return;
				}
		}
	return;
}

/**
 * 
 */
function saveAllEdittingRow()
{
	 for (var i = 0; i < listEditedRowID.length + 1; i++) {
	    	if (isEditting(listEditedRowID[i])) {
	    		//save to client
				$(jQGridId).jqGrid('saveRow', listEditedRowID[i]);
			}
	    }
}

/**
 * Change CSS Style to mark the row is removed
 */
function markRemovedRow(rowId)
{
	$("#"+ rowId).find("td").css("text-decoration", "line-through");
	$("#"+ rowId).find("td").css("color", "grey");
}

/**
 * Go through the grid and change the style of removed row
 */
function setRemoveRow()
{
	var gridIds = $(jQGridId).jqGrid("getDataIDs");
	for (var i=0; i<gridIds.length;++i)
		{
			if (getGridData(gridId,gridIds[i]).Status === "-1")
				markRemovedRow(gridIds[i]);
		}
}

/**
 * Trigger reload grid on client side
 */
function reloadOnClientSide()
{
	jQuery(jQGridId).trigger("reloadGrid");
}

/**
 * Trigger reload grid on server side
 */
function reloadOnServerSide()
{
	//reset utility value
	oldDataList = new Array();
    listEditedRowID = new Array();
    inValidRowId = new Array();
    //load grid data
	jQuery(jQGridId).jqGrid('setGridParam', {datatype:'json'}).trigger('reloadGrid');
	disableCustomButton(saveAllButtonId);
//	document.location.reload(true);
}

/**
 * This function handle what happen when user click on refresh button
 */
function reloadButtonHandler()
{
	reloadOnServerSide();
}

/**
 * Validate: 
 * 	+ If any row which has empty link/title exist
 *  + If the format of the inputed link is correct
 */
function validateData()
{
	//reset inValidRowId list
	unMarkAsInvalid(inValidRowId);
	inValidRowId = new Array();
	var gridIds = $(jQGridId).jqGrid("getDataIDs");
	for (var i=0; i<gridIds.length;++i)
		{
			var data = getGridData(gridId,gridIds[i]);
			if (parseInt(data.Status) >-1 )
				{
					if (trim(data.Link) === "" || trim(data.Title)===""||!isUrl(data.Link))
					{
						inValidRowId.push(gridIds[i]);
						//alert
						openAlert();
						break;
					} else if (!isFilePath(data.Link)){
						inValidRowId.push(gridIds[i]);
						//alert
						openAlert("filepath-error-dialog");
						break;
					};
				};
		}
	if (inValidRowId.length>0)
		{
			markAsInvalid(inValidRowId);
			return false;
		}
	return true;
}

/**
 * Validate if an URL is in correct format or not
 * @param url
 * @returns
 */
var strRegex = "(^((http|https|ftp|file)\://))|(^(file:///))|(^(\\\\))|(^(/))";
function isUrl(url) {
     var re=new RegExp(strRegex);
     return re.test(url);
	}

var fileRegex = "(^(file://))|(^(\\\\))|(^(/))";
function isFilePath(url) {
	var re=new RegExp(strRegex);
    var isFile =  re.test(url);
    if (isFile) {
    	var pieces = url.split('\\');
    	var filename = pieces[pieces.length-1];
    	isFile = filename.indexOf('.') > 0;
    	
    	if (!isFile) {
    		pieces = url.split('/');
        	filename = pieces[pieces.length-1];
        	isFile = filename.indexOf('.') > 0;
    	}
    }
    
    return isFile;
}

/**
 * 
 * @param rowId
 */
function unRemoveRow(rowId)
{
	$("#"+ rowId).find("td").css("text-decoration", "none");
	$("#"+ rowId).find("td").css("color", "#336699");
}